<template>
  <div class="card-file-container">
    <div
      v-for="(group, index) in fileGroup"
      :key="index"
      :style="{ paddingBottom: fileContainerHeight }"
      class="file-container"
    >
      <div ref="contentRef" class="file-content" @click.stop="()=>{}">
        <template>
          <div
            v-for="file in group"
            :key="file.uid || file.url"
            :style="{width: fileItemWidth, height: getHeight()}"
            class="file-item close-icon-hover">
            <template v-if="file.url">
              <el-tooltip :open-delay="800" placement="top" effect="dark">
                <div slot="content" class="tip-content">
                  <div class="tip-left">
                    <div class="name" @click="downloadFile(file.url, file.name, true)">文件名：{{ file.name }}</div>
                    <div v-if="file.time" class="time">上传时间：{{ file.time | format('YYYY-MM-DD HH:mm:ss') }}</div>
                  </div>
                  <span class="tip-right" @click="downloadFile(file.url, file.name, true)">下载</span>
                </div>
                <div v-if="isImg(file.name)" class="file-item-box">
                  <el-image
                    v-if="!showMobilePage"
                    :src="file.url"
                    fit="cover"
                    style="width: 100%; height: 100%;cursor: zoom-in;"
                    alt=""
                    @click="openPreview(file)"
                  />
                  <el-image
                    v-else
                    :src="file.url"
                    :preview-src-list="previewFiles"
                    fit="cover"
                    style="width: 100%; height: 100%;cursor: zoom-in;"
                    alt=""
                  />
                </div>
                <div v-else-if="isVideo(file.name)" class="file-item-box">
                  <VideoPlayer
                    :src="file.url"
                    :play-width="60"
                    width="100%"
                    height="100%"
                  />
                  <div class="video-mask" @click.stop="openPreview(file)" />
                </div>
                <div v-else class="file-item-box" @click="downloadFile(file.url, file.name)">
                  <el-image :src="folderIcon" fit="contain" class="file-item-icon" alt="" />
                </div>
              </el-tooltip>
              <i v-if="isEdit" class="el-icon-close close-icon" @click="removeFile(file)"/>
            </template>
            <!-- 上传失败文件 -->
            <template v-else-if="file.isError">
              <el-tooltip :content="`文件名：${file.name}`" :open-delay="800" placement="top">
                <div class="file-error-item-box">
                  <template v-if="previewImgUrl(file)">
                    <img v-if="previewImgUrl(file).type.includes('image')" :src="previewImgUrl(file).url" class="err-img" alt="">
                    <video v-else :src="previewImgUrl(file).url" class="err-img" alt=""/>
                  </template>
                  <div class="text-container">
                    <i class="reupload-icon el-icon-refresh-right" @click="reUpload(file)"/>
                    <div>上传失败</div>
                    <div>重新上传</div>
                  </div>
                  <i v-if="isEdit" class="el-icon-close close-icon" @click="removeError(file)"/>
                </div>
              </el-tooltip>
            </template>
            <!-- 其他附件 -->
            <div v-else-if="file.otherFileArr && file.otherFileArr.length" class="other-filer-content" @click.stop="handleViewOtherFiles">
              <el-image :src="folderIcon" fit="contain" class="file-item-icon" alt="" />
              <FileShowList ref="otherFilesRef" :file-list="file.otherFileArr" :show-delete="isEdit" @removeFileList="otherFileRemove">
                <template slot="fileTitle">
                  <span class="file-title">{{ `${file.otherFileArr.length}个文件` }}</span>
                </template>
              </FileShowList>
            </div>
            <template v-if="file.type === 'preview'">
              <div v-loading="true" style="width: 100%;height: 100%;"/>

              <div v-if="filePercent[file.name]" class="upload-progress">
                <el-progress :percentage="Number(filePercent[file.name])" :show-text="false" />
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>
    <div v-if="moreBtnVisible" class="toggle-btn" @click.stop="showStatusToggle">
      {{ showAll ? '收起' : `展开全部(+${allListLen - 9})` }}
      <i :class="[ showAll ? 'el-icon-arrow-up' : 'el-icon-arrow-down' ]" />
    </div>
    <el-dialog
      :visible="videoVisible"
      :before-close="handleVideoClose"
      :close="handleVideoClose"
      show-close
      append-to-body
      class="large-common-dialog-size video-dialog-container"
    >
      <VideoPlayer
        :src="currPlayVideoUrl"
        :play-width="120"
        autoplay
        width="60vw"
        height="33.7vw"
      />
    </el-dialog>
  </div>
</template>

<script>
import * as dd from 'dingtalk-jsapi';
import { getExplorer, generateUUID } from '@/utils/tools';
import { downloadFile, openNewWindow } from '@/utils';
import { format } from '@/filters/date';
import FileShowList from '@/components/CreateOrder/fileShowList';
import VideoPlayer from '@/components/Common/upAttachment/VideoPlayer';
import folderIcon from '@/assets/legal/folder_icon.png';
import { mapState } from 'vuex';
export default {
  name: 'CardThumbnailFiles',
  components: {
    VideoPlayer,
    FileShowList
  },
  filters: { format },
  props: {
    fileList: {
      type: Array,
      default: () => []
    },
    isEdit: {
      type: Boolean,
      default: false
    },
    filePercent: {
      type: Object,
      default: () => ({})
    },
    errorFileList: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      folderIcon,
      showAll: false,
      videoVisible: false,
      fileGroup: [],
      currPlayVideoUrl: ''
    };
  },
  computed: {
    ...mapState({
      'showMobilePage': state => state.app.showMobilePage
    }),
    moreBtnVisible() {
      const errorFileLen = this.errorFileList ? this.errorFileList.length : 0;
      const imgAndVideoNum = this.fileList.filter(file => (this.isImg(file.name) || this.isVideo(file.name))).length;
      return (imgAndVideoNum + errorFileLen) > (this.hasOtherFiles ? 8 : 9);
    },
    hasOtherFiles() { // 存在非图片和视频的文件时，以一行3列的方式展示
      return !this.fileList.every(file => (this.isImg(file.name) || this.isVideo(file.name)));
    },
    /**
     * 返回文件列表和错误文件列表的长度总和
     */
    allListLen() {
      const fileLen = this.fileList ? this.fileList.length : 0;
      const errorFileLen = this.errorFileList ? this.errorFileList.length : 0;
      return fileLen + errorFileLen;
    },
    fileContainerHeight() {
      if (this.hasOtherFiles) return 'calc(33.3% - 4px)';
      return this.allListLen === 1 ? '100%' : ([2, 4].includes(this.allListLen) ? 'calc(50% - 4px)' : 'calc(33.3% - 4px)');
    },
    fileItemWidth() {
      if (this.hasOtherFiles) return 'calc((100% - 8px) / 3)';
      const fileLengthToWidthMap = {
        1: '100%',
        2: 'calc((100% - 4px) / 2)',
        3: 'calc((100% - 8px) / 3)',
        4: 'calc((100% - 4px) / 2)'
      };
      return fileLengthToWidthMap[this.allListLen] || 'calc((100% - 8px) / 3)';
    },
    // 预览图
    previewFiles() {
      const previewArr = [];
      this.fileList.forEach(file => {
        this.isImg(file.name) && previewArr.push(file.url);
      });
      return previewArr;
    }
  },
  watch: {
    fileList: {
      handler(list) {
        this.setViewFiles(list);
      },
      immediate: true,
      deep: true
    },
    errorFileList: {
      handler() {
        this.setViewFiles(this.fileList);
      },
      immediate: true,
      deep: true
    }
  },
  methods: {
    openPreview(file) {
      const imgData = this.fileList.filter(it => this.isImg(it.name) || this.isVideo(it.name));
      const selectIndex = imgData.findIndex(it => it.uid === file.uid);
      if (selectIndex === -1) return;
      this.$store.dispatch('ToggleImageViewer', {
        showImageViewer: true,
        imgData,
        selectIndex
      });
    },
    isImg(name) {
      const reg = /(\.(gif|png|jpg|jpeg|webp|bmp|tif))$/i;
      return reg.test(name);
    },
    isVideo(name) {
      const reg = /(\.(mp4|mkv|webm|avi|flv|mov|wmv))$/i;
      return reg.test(name);
    },
    isDoc(name) {
      const reg = /(\.(doc|docx|xls|xlsx|xlsm|ppt|pptx|txt|pdf|odt))$/i;
      return reg.test(name);
    },
    isAudio(name) {
      const reg = /(\.(mp3|wav|aac|flac|ogg|m4a))$/i;
      return reg.test(name);
    },
    isPackage(name) {
      const reg = /(\.(zip|rar|7z|tar|gz|bz2))$/i;
      return reg.test(name);
    },
    isDingTalk() {
      const currentExplorer = getExplorer() || window.navigator.userAgent;
      return currentExplorer === 'DingTalk';
    },
    dinkDownload(url, name) {
      if (this.isDingTalk()) {
        dd.biz.util.openLink({
          url: url + '?attname=' + name, // 要打开链接的地址
          onSuccess: function(result) {
          }
        });
      } else {
        downloadFile(url, name);
      }
    },
    getHeight() {
      const item = this.$refs.contentRef;
      if (this.fileList) {
        if (item) {
          if (this.hasOtherFiles) return ((item.offsetWidth - 8) / 3) + 'px';
          const fileLengthToHeightMap = {
            1: '100%',
            2: (item.offsetWidth - 4) / 2,
            3: (item.offsetWidth - 8) / 3,
            4: (item.offsetWidth - 4) / 2
          };
          return (fileLengthToHeightMap[this.allListLen] || ((item.offsetWidth - 8) / 3)) + 'px';
        }
      }
      return '100%';
    },
    showStatusToggle() {
      this.showAll = !this.showAll;
      this.setViewFiles(this.fileList);
      this.$emit('showStatusToggle');
    },
    setViewFiles(list) {
      let result = [];
      // 以 视频 > 图片 > 其他文件(合并显示) 的优先级，生成二维数组
      const fileList = _.cloneDeep(list);
      const errorFileList = _.cloneDeep(this.errorFileList || []);
      if (fileList.length || errorFileList.length) {
        const videoArr = [];
        const imgArr = [];
        const otherFileData = { otherFileArr: [], uid: generateUUID() };
        fileList.forEach(file => {
          if (this.isVideo(file.name)) {
            videoArr.push(file);
          } else if (this.isImg(file.name)) {
            imgArr.push(file);
          } else {
            otherFileData.otherFileArr.push(file);
          }
        });
        let sortArr = [...videoArr, ...imgArr];

        const hasOtherFile = !!otherFileData.otherFileArr.length;
        hasOtherFile && sortArr.push(otherFileData);

        // 错误显示
        if (errorFileList && errorFileList.length) {
          errorFileList.forEach((i, index) => {
            i.errIndex = index;
            i.isError = true;
            i.uid = generateUUID();
            sortArr.push(i);
          });
        }
        if (!this.showAll && sortArr.length > 9) {
          sortArr = sortArr.slice(0, 9);
        } else {
          this.showAll = true;
        }
        // 只要有除了图片和视频以外的文件时，就以每行3列的方式展示
        if (!hasOtherFile && sortArr.length <= 3) {
          result = [sortArr];
        } else if (!hasOtherFile && sortArr.length === 4) {
          result = [sortArr.slice(0, 2), sortArr.slice(2, 4)];
        } else {
          const time = this.showAll ? Math.ceil(sortArr.length / 3) : 3;
          for (let i = 0; i < time; i++) {
            result.push(sortArr.slice(i * 3, (i + 1) * 3));
          }
        }
      }

      this.fileGroup = result;
      this.$forceUpdate();
    },
    viewDoc(url, name) {
      try {
        const timestamp = (new Date()).valueOf();
        const random = Math.ceil(Math.random() * 10);
        const lists = name.split('.');
        const fileName = `${timestamp}${random}.` + lists[lists.length - 1];
        const previewUrl = `${url}#&fullfilename=${fileName}`;
        const officeUrl = 'http://fileview.feibo.com/onlinePreview?url=' + encodeURIComponent(btoa(previewUrl));
        openNewWindow(officeUrl);
      } catch (error) {
        this.dinkDownload(url, name);
      }
    },
    videoPlay(file) {
      this.currPlayVideoUrl = file.url;
      this.videoVisible = true;
    },
    handleVideoClose() {
      this.currPlayVideoUrl = '';
      this.videoVisible = false;
    },
    downloadFile(url, name, download = false) {
      if (download) {
        this.dinkDownload(url, name);
        return;
      }
      if (this.isImg(name)) {
        if (this.isDingTalk()) {
          dd.biz.util.previewImage({
            urls: [url], // 图片地址列表
            current: url, // 当前显示的图片链接
            onFail: function(err) {
              // 调用失败时回调
              window.open(url);
              console.log(err);
            }
          });
        } else {
          window.open(url);
        }
      } else if (this.isDoc(name)) {
        this.viewDoc(url, name);
      } else {
        this.dinkDownload(url, name);
      }
    },
    handleViewOtherFiles() {
      if (this.$refs['otherFilesRef'][0] && !this.$refs['otherFilesRef'][0].dialogVisible) {
        this.$refs['otherFilesRef'][0].dialogVisible = true;
      }
    },
    otherFileRemove(data) {
      this.removeFile(data.file);
    },
    removeFile(item) {
      const index = this.fileList.findIndex(file => (file.uid === item.uid || file.url === item.url));
      this.$emit('removeFile', item, index);
    },
    removeError(item) {
      this.$emit('removeError', item, item.errIndex);
    },
    reUpload(item) {
      this.$emit('reUpload', item, item.errIndex);
    },
    previewImgUrl(item) {
      const formData = item.formData;
      const file = formData.get('fileData');
      if (file && (file.type.includes('image') || file.type.includes('video'))) {
        return {
          url: window.URL.createObjectURL(file),
          type: file.type
        };
      }
      return null;
    }
  }
};
</script>

<style scoped lang="scss">
.card-file-container {
  width: 100%;
  margin-top: 12px;
  .file-container {
    width: 100%;
    position: relative;
    margin-bottom: 4px;
    .file-content {
      position: absolute;
      display: flex;
      width: 100%;
      height: 100%;
      flex-wrap: wrap;
      gap: 4px;
      .file-item {
        position: relative;
        border-radius: 8px;
        overflow: hidden;
        height: 100%;
        .file-item-box {
          display: flex;
          align-items: center;
          justify-content: center;
          background-color: #ebeefd;
          width: 100%;
          height: 100%;
          cursor: zoom-in;
          position: relative;
          &:hover {
            filter: brightness(0.7) opacity(80%);
          }
        }
        .file-error-item-box {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 100%;
          height: 100%;
          position: relative;
          line-height: 1.2;
          .text-container {
            color: #fff;
            font-size: 12px;
            background-color: rgba(0,0,0,0.5);
            width: 100%;
            height: 100%;
            position: relative;
            z-index: 2;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            font-weight: bold;
          }
          .reupload-icon {
            font-size: 18px;
            margin-bottom: 4px;
            cursor: pointer;
          }
          .err-img {
            position: absolute;
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
        }
        .video-mask {
          position: absolute;
          width: 100%;
          height: 100%;
          top: 0;
          left: 0;
          z-index: 2;
        }
      }
      .file-item-icon {
        width: 40%;
        height: 40%;
      }
      .other-filer-content {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        height: 100%;
        background: #f0f2f5;
        cursor: pointer;
        .file-title {
          font-size: 12px;
          color: #333;
        }
        &::v-deep {
          .file-list, .file-list-title {
            height: 24px;
            line-height: 24px !important;
          }
        }
        &:hover {
          .file-title {
            color: #406eff;
          }
        }
      }
    }
  }
  .close-icon-hover {
    &:hover {
      .close-icon {
        display: flex !important;
      }
    }
  }
  .upload-progress {
    position: absolute;
    bottom: 0px;
    left: 0;
    width: 100%;
    z-index: 2002;
    padding: 0 10px 5px 10px;
  }
  .close-icon {
    position: absolute;
    right: 0;
    top: 0;
    color: #fff;
    background-color: #406eff;
    border-radius: 100%;
    width: 16px;
    height: 16px;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    cursor: pointer;
    z-index: 10000;
    display: none;
  }
  .toggle-btn {
    background-color: #ebeefd;
    color: #406eff;
    text-align: center;
    border-radius: 8px;
    user-select: none;
    cursor: pointer;
    height: 24px;
    font-size: 12px;
    line-height: 24px;
    > i {
      margin-left: 4px;
    }
  }
}
.tip-content{
  max-width: 220px;
  display: flex;
  .tip-left{
    .name{
      margin-bottom: 6px;
      cursor: pointer;
      word-break: break-all;
    }
    .time{
      white-space: nowrap;
    }
  }
  .tip-right{
    white-space: nowrap;
    color: #406EFF;
    margin-left: 8px;
    cursor: pointer;
  }
}
.video-dialog-container {
  &::v-deep {
    .el-dialog {
      width: 60vw !important;
      height: 33.7vw !important;
      background: transparent;
    }
    .el-dialog__body {
      padding: 0 !important;
    }
    video {
      width: 100%;
      height: 100%;
    }
  }
}
</style>
